package com.tfleo.mealssenger;

import com.tfleo.mealssenger.R;
import com.tfleo.mealssenger.service.ChatService;
import com.tfleo.mealssenger.utility.NetworkTools;
import com.tfleo.mealssenger.utility.SecurityTools;

import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;

import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Typeface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Settings.Secure;
import android.text.method.PasswordTransformationMethod;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ViewSwitcher;

/**
 * Application login page.
 * 
 * @author Theodore Felix Leo
 *
 */
public class LoginActivity extends Activity {
	private static final String TAG = "LoginActivity";
	private static final int REGISTER_REQUEST = 1;
	private static final String LOGOUT = "logout";

	private SharedPreferences mSharedPref;
	private SharedPreferences.Editor mPrefEditor;
	private Context mContext;

	private ViewSwitcher vSwitcher;
	private String mAuth;

	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.login_layout);
		mContext = this;
		mAuth = Secure.getString(this.getContentResolver(), Secure.ANDROID_ID); //for authentication
		mSharedPref = getSharedPreferences(Main.USER_DATA, MODE_PRIVATE);
		mPrefEditor = mSharedPref.edit();
		vSwitcher = (ViewSwitcher) findViewById(R.id.switcher);
		
		//Handle logout event
		Bundle extras = getIntent().getExtras();
		if(extras != null) {
			if(extras.getBoolean(LOGOUT)) {
				resetUserData();

				if(mSharedPref.getBoolean(Main.ONLINE, false)) {
					mPrefEditor.putBoolean(Main.ONLINE, false);
					mPrefEditor.commit();
					ChatService.actionStop(getApplicationContext());
				}
			}
		}

		if(mSharedPref.getBoolean(Main.REMEMBER_LOGIN, false)) {
			if(NetworkTools.isNetworkAvailable(mContext)){
				GetUserDataTask task = new GetUserDataTask();
				task.execute();
			} else {
				Toast.makeText(mContext, "Network is currently unavailable", 
						Toast.LENGTH_LONG).show();
				Log.e(TAG, "[NetworkProblem] Network is unavailable");
			}
		} else {
			resetUserData();

			vSwitcher.showNext();
			final EditText userBox = (EditText) findViewById(R.id.email_entry);
			final EditText passwordBox = (EditText) findViewById(R.id.password_entry);
			passwordBox.setTypeface(Typeface.DEFAULT);
		    passwordBox.setTransformationMethod(new PasswordTransformationMethod());
			final TextView register = (TextView) findViewById(R.id.register);
			
			register.setOnClickListener(new OnClickListener() {
				public void onClick(View v) {
					startActivityForResult(new Intent(LoginActivity.this, 
							RegisterActivity.class), REGISTER_REQUEST);
				}
			});

			final Button loginBtn = (Button) findViewById(R.id.login_btn);
			loginBtn.setOnClickListener(new OnClickListener() {
				public void onClick(View v) {
					if(userBox.getText().toString().isEmpty()) {
						Toast.makeText(getApplicationContext(), "Invalid user name", 
								Toast.LENGTH_SHORT).show();
					} else if(NetworkTools.isNetworkAvailable(mContext)){
						VerifyLoginTask task = new VerifyLoginTask();
						task.execute(new String[] {
								userBox.getText().toString(), passwordBox.getText().toString()});
					} else {
						Toast.makeText(mContext, "Network is currently unavailable", 
								Toast.LENGTH_LONG).show();
						Log.e(TAG, "[NetworkProblem] Network is unavailable");
						finish();
					}
				}
			});

			final CheckBox rememberCheck = (CheckBox) findViewById(R.id.remember_checkbox);
			rememberCheck.setOnClickListener(new OnClickListener() {
				public void onClick(View v) {
					if (((CheckBox) v).isChecked()) {
						mPrefEditor.putBoolean(Main.REMEMBER_LOGIN, true);
					} else {
						mPrefEditor.putBoolean(Main.REMEMBER_LOGIN, false);
					}
					mPrefEditor.commit();
				}
			});
		} 
	}

	@Override
	protected void onDestroy() {
		//task.cancel(true);
		super.onDestroy();
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);

		if(requestCode == REGISTER_REQUEST && resultCode == RESULT_OK) {
			Toast.makeText(mContext, "Registration successful!", Toast.LENGTH_SHORT).show();
		}
	}

	private boolean verifyLogin(String email, String password) {
		HttpClient httpclient = new DefaultHttpClient();
		HttpPost httppost = new HttpPost(Main.SERVER_URL + "login.php");

		try {
			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
			nameValuePairs.add(new BasicNameValuePair("email", email));
			nameValuePairs.add(new BasicNameValuePair("password", password));
			nameValuePairs.add(new BasicNameValuePair("auth", mAuth));
			httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

			// Execute HTTP Post Request
			ResponseHandler<String> responseHandler = new BasicResponseHandler();
			String body = httpclient.execute(httppost, responseHandler);
			JSONObject jo = new JSONObject(body);

			if(jo.getInt("code") == 1) {
				JSONObject response = jo.getJSONObject("response");
				
				mPrefEditor.putInt(Main.USER_ID, response.getInt("id"));
				mPrefEditor.putString(Main.USER_NAME, response.getString("name"));
				mPrefEditor.putString(Main.USER_IMAGE, response.getString("image"));
				mPrefEditor.putInt(Main.LAST_CHECKIN_ID, response.optInt("last_checkin"));
				mPrefEditor.putInt(Main.LAST_MEALUP_ID, response.optInt("last_mealup"));
				mPrefEditor.putInt(Main.LAST_CHECKIN_PLACEID, response.optInt("place_id"));
				mPrefEditor.putString(Main.LAST_CHECKIN_PLACENAME, response.optString("place_name"));
				//TODO: Remove need of chat id
				mPrefEditor.putString(Main.CHAT_ID, Integer.toString(response.getInt("id")));
				//TODO: Validate value unchanged as long as user is logged in
				mPrefEditor.putString(Main.TOKEN, SecurityTools.encrypt(SecurityTools.MASTER_KEY, password));
				mPrefEditor.putString(Main.EMAIL, email);
				mPrefEditor.commit();
				return true;
			} else {
				return false;
			}
		} catch(Exception e){
			e.printStackTrace();
		}

		return false;
	}

	private boolean getUserData(int userId) {
		if(userId == 0) return false;
		try {
			URL url = new URL(Main.SERVER_URL + "user/" + userId + "&me=" + userId + "&auth=" + mAuth);
			URLConnection conn = url.openConnection();
			BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));

			String body;
			if((body = in.readLine()) != null) {
				JSONObject jo = new JSONObject(body);
				if(jo.getInt("code") == 1) {
					JSONObject response = jo.getJSONObject("response");
					
					mPrefEditor.putInt(Main.USER_ID, userId);
					mPrefEditor.putString(Main.USER_NAME, response.getString("name"));
					mPrefEditor.putString(Main.USER_IMAGE, response.getString("image"));
					mPrefEditor.putInt(Main.LAST_CHECKIN_ID, response.optInt("last_checkin"));
					mPrefEditor.putInt(Main.LAST_MEALUP_ID, response.optInt("last_mealup"));
					mPrefEditor.putInt(Main.LAST_CHECKIN_PLACEID, response.optInt("place_id"));
					mPrefEditor.putString(Main.LAST_CHECKIN_PLACENAME, response.optString("place_name"));
					mPrefEditor.putString(Main.CHAT_ID, Integer.toString(userId));
					mPrefEditor.commit();
					return true;
				}
			} else {
				return false;
			}
		} catch (Exception e) {
			e.printStackTrace();
		} 
		return false;
	}

	private class VerifyLoginTask extends AsyncTask<String, Void, Boolean> {
		private ProgressDialog mProgressDialog;

		@Override    
		protected void onPreExecute() {       
			super.onPreExecute();
			mProgressDialog = new ProgressDialog(mContext);
			mProgressDialog.setMessage("Loading...");
			mProgressDialog.setCancelable(false);
			mProgressDialog.setIndeterminate(true);
			mProgressDialog.show();
		}
		
		@Override
		protected Boolean doInBackground(String... params) {
			String email = params[0];
			String password = params[1];
			
			Log.i(TAG, "Logging in to Mealssenger...");
			return verifyLogin(email, password); 
		}

		@Override
		protected void onPostExecute(Boolean result) {
			if(result) {
				mProgressDialog.dismiss();
				Intent i = new Intent(LoginActivity.this, Main.class);
				i.putExtra("tab", 1);
				LoginActivity.this.startActivity(i);
				LoginActivity.this.finish();
			} else {
				mProgressDialog.dismiss();
				Toast.makeText(getApplicationContext(), "Failed to login", 
						Toast.LENGTH_LONG).show();
				Log.e(TAG, "[CommunicationError] Failed to login");
			}
		}

	}

	private class GetUserDataTask extends AsyncTask<Void, Void, Boolean> {
		private ProgressDialog mProgressDialog;

		@Override    
		protected void onPreExecute() {       
			super.onPreExecute();
			mProgressDialog = new ProgressDialog(mContext);
			mProgressDialog.setMessage("Loading...");
			mProgressDialog.setCancelable(false);
			mProgressDialog.setIndeterminate(true);
			mProgressDialog.show();
		}

		@Override
		protected Boolean doInBackground(Void... params) {	
			Log.i(TAG, "Fetching user data...");
			return getUserData(mSharedPref.getInt(Main.USER_ID, 0));
		}

		@Override
		protected void onPostExecute(Boolean result) {
			if(result) {
				mProgressDialog.dismiss();
				Intent i = new Intent(LoginActivity.this, Main.class);
				i.putExtra(Main.TAB_POS, 1);
				LoginActivity.this.startActivity(i);
				LoginActivity.this.finish();
			} else {
				Toast.makeText(getApplicationContext(), "Failed to fetch user data", 
						Toast.LENGTH_LONG).show();
				Log.e(TAG, "[CommunicationError] Failed to fetch user data");
				mProgressDialog.dismiss();
				resetUserData(); //Clear everything, try to do clean start
				//TODO: clean start login page
				finish();
			}
		}
	}
	
	private void resetUserData() {
		mPrefEditor.putBoolean(Main.REMEMBER_LOGIN, false);
		mPrefEditor.putInt(Main.USER_ID, 0);
		mPrefEditor.putString(Main.USER_NAME, "");
		mPrefEditor.putString(Main.USER_IMAGE, "");
		mPrefEditor.putInt(Main.LAST_MEALUP_ID, 0);
		mPrefEditor.putInt(Main.LAST_CHECKIN_ID, 0);
		mPrefEditor.putInt(Main.LAST_CHECKIN_PLACEID, 0);
		mPrefEditor.putString(Main.LAST_CHECKIN_PLACENAME, "");
		
		mPrefEditor.putString(Main.CHAT_ID, "");
		mPrefEditor.putString(Main.TOKEN, "");
		mPrefEditor.putString(Main.EMAIL, "");
		mPrefEditor.commit();
	}


}
